import time
import hashlib

class Block:
    # 初始化区块
    def __init__(self, index, previous_hash, time_stamp, data, nonce, hash):
        self.index = index  # 区块的索引
        self.previous_hash = previous_hash  # 上一个区块的哈希值
        self.time_stamp = time_stamp  # 区块的时间戳
        self.data = data  # 区块的数据
        self.nonce = nonce  # 工作量证明的随机数
        self.hash = hash  # 区块的哈希值

    def calculate_hash(self):
        Block_string = f"{self.index} {self.previous_hash} {self.time_stamp} {self.data} {self.nonce}".encode()
        return hashlib.sha256(Block_string).hexdigest()

    # 工作量证明算法
    def proof_of_work(self, previous_hash, data, nonce):
        target_difficulty = "0000"  # 目标难度，即哈希值的前4位必须是0
        hash = hashlib.sha256(f"{previous_hash} {data} {nonce}".encode()).hexdigest()  # 计算哈希值
        while hash[:4] != target_difficulty:  # 如果哈希值的前4位不是0，则增加随机数并重新计算哈希值
            nonce += 1
            hash = hashlib.sha256(f"{previous_hash} {data} {nonce}".encode()).hexdigest()
        return hash  # 返回有效哈希值

# 创建一个创世区块
def create_genesis_block():
    return Block(0, "0", int(time.time()), "Genesis Block", 0, "0")  # 返回一个区块对象，参数分别为：区块索引、前一个区块的哈希值、当前时间、区块数据、工作量证明的随机数、当前区块的哈希值

# 创建下一个区块
def create_next_block(previous_block, data):
    index = previous_block.index + 1  # 获取前一个区块的索引加1
    time_stamp = int(time.time())  # 获取当前时间戳
    previous_hash = previous_block.hash  # 获取前一个区块的哈希值
    nonce = 0  # 初始化工作量证明的随机数
    hash = previous_block.proof_of_work(previous_hash, data, nonce)  # 计算当前区块的哈希值
    return Block(index, previous_hash, time_stamp, data, nonce, hash)  # 返回新的区块

# 创建类
class Blockchain:
    # 初始化区块链，创建一个包含创世块的链
    def __init__(self):
        self.chain = [create_genesis_block()]

    # 获取链中的最后一个区块
    def get_last_block(self):
        return self.chain[-1]

    # 添加新区块
    def add_block(self, new_block):
        new_block.hash = new_block.calculate_hash()
        self.chain.append(new_block)

    # 校验函数(校验区块链是否合法)
    def is_chain_valid(self):
        for i in range(1, len(self.chain)):  # 遍历区块链，从第二个区块开始
            current_block = self.chain[i]  # 获取当前区块
            previous_block = self.chain[i - 1]  # 获取前一个区块

            if current_block.hash != current_block.calculate_hash():  # 校验当前区块的hash值是否正确
                return False

            if current_block.previous_hash != previous_block.hash:  # 校验当前区块的前一个区块的hash值是否与前一个区块的hash值相同
                return False

        return True  # 如果所有校验都通过，则返回True

# 实例化区块链
Blockchain = Blockchain()

# 添加新的区块
new_block = create_next_block(Blockchain.get_last_block(), "李佳奇给杨鑫大帅哥100个比特币")
Blockchain.add_block(new_block)

new_block = create_next_block(Blockchain.get_last_block(), "李佳奇给杨鑫大帅哥200个比特币")
Blockchain.add_block(new_block)

print("Is chain valid?", Blockchain.is_chain_valid())

for block in Blockchain.chain:
    print(f"区块索引：{block.index}[{block.time_stamp}]")
    print(f"前一个区块哈希：{block.previous_hash}")
    print(f"区块数据：{block.data}")
    print(f"区块哈希：{block.hash}")
    print(f"工作量证明的随机数：{block.nonce}")
